home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / metamail / tahoe / cmd2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-18  |  10.7 KB  |  595 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifdef notdef
  14. static char sccsid[] = "@(#)cmd2.c    5.5 (Berkeley) 2/18/88";
  15. #endif /* notdef */
  16.  
  17. #include "rcv.h"
  18. #include <sys/stat.h>
  19. #include <sys/wait.h>
  20.  
  21. /*
  22.  * Mail -- a mail program
  23.  *
  24.  * More user commands.
  25.  */
  26.  
  27. /*
  28.  * If any arguments were given, go to the next applicable argument
  29.  * following dot, otherwise, go to the next applicable message.
  30.  * If given as first command with no arguments, print first message.
  31.  */
  32.  
  33. next(msgvec)
  34.     int *msgvec;
  35. {
  36.     register struct message *mp;
  37.     register int *ip, *ip2;
  38.     int list[2], mdot;
  39.  
  40.     if (*msgvec != NULL) {
  41.  
  42.         /*
  43.          * If some messages were supplied, find the 
  44.          * first applicable one following dot using
  45.          * wrap around.
  46.          */
  47.  
  48.         mdot = dot - &message[0] + 1;
  49.  
  50.         /*
  51.          * Find the first message in the supplied
  52.          * message list which follows dot.
  53.          */
  54.  
  55.         for (ip = msgvec; *ip != NULL; ip++)
  56.             if (*ip > mdot)
  57.                 break;
  58.         if (*ip == NULL)
  59.             ip = msgvec;
  60.         ip2 = ip;
  61.         do {
  62.             mp = &message[*ip2 - 1];
  63.             if ((mp->m_flag & MDELETED) == 0) {
  64.                 dot = mp;
  65.                 goto hitit;
  66.             }
  67.             if (*ip2 != NULL)
  68.                 ip2++;
  69.             if (*ip2 == NULL)
  70.                 ip2 = msgvec;
  71.         } while (ip2 != ip);
  72.         printf("No messages applicable\n");
  73.         return(1);
  74.     }
  75.  
  76.     /*
  77.      * If this is the first command, select message 1.
  78.      * Note that this must exist for us to get here at all.
  79.      */
  80.  
  81.     if (!sawcom)
  82.         goto hitit;
  83.  
  84.     /*
  85.      * Just find the next good message after dot, no
  86.      * wraparound.
  87.      */
  88.  
  89.     for (mp = dot+1; mp < &message[msgCount]; mp++)
  90.         if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
  91.             break;
  92.     if (mp >= &message[msgCount]) {
  93.         printf("At EOF\n");
  94.         return(0);
  95.     }
  96.     dot = mp;
  97. hitit:
  98.     /*
  99.      * Print dot.
  100.      */
  101.  
  102.     list[0] = dot - &message[0] + 1;
  103.     list[1] = NULL;
  104.     return(type(list));
  105. }
  106.  
  107. /*
  108.  * Save a message in a file.  Mark the message as saved
  109.  * so we can discard when the user quits.
  110.  */
  111. save(str)
  112.     char str[];
  113. {
  114.  
  115.     return(save1(str, 1));
  116. }
  117.  
  118. /*
  119.  * Copy a message to a file without affected its saved-ness
  120.  */
  121. copycmd(str)
  122.     char str[];
  123. {
  124.  
  125.     return(save1(str, 0));
  126. }
  127.  
  128. /*
  129.  * Save/copy the indicated messages at the end of the passed file name.
  130.  * If mark is true, mark the message "saved."
  131.  */
  132. save1(str, mark)
  133.     char str[];
  134. {
  135.     register int *ip, mesg;
  136.     register struct message *mp;
  137.     char *file, *disp, *cmd;
  138.     int f, *msgvec, lc, t;
  139.     long cc;
  140.     FILE *obuf;
  141.     struct stat statb;
  142.  
  143.     cmd = mark ? "save" : "copy";
  144.     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  145.     if ((file = snarf(str, &f)) == NOSTR)
  146.         return(1);
  147.     if (!f) {
  148.         *msgvec = first(0, MMNORM);
  149.         if (*msgvec == NULL) {
  150.             printf("No messages to %s.\n", cmd);
  151.             return(1);
  152.         }
  153.         msgvec[1] = NULL;
  154.     }
  155.     if (f && getmsglist(str, msgvec, 0) < 0)
  156.         return(1);
  157.     if ((file = expand(file)) == NOSTR)
  158.         return(1);
  159.     printf("\"%s\" ", file);
  160.     fflush(stdout);
  161.     if (stat(file, &statb) >= 0)
  162.         disp = "[Appended]";
  163.     else
  164.         disp = "[New file]";
  165.     if ((obuf = fopen(file, "a")) == NULL) {
  166.         perror(NOSTR);
  167.         return(1);
  168.     }
  169.     cc = 0L;
  170.     lc = 0;
  171.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  172.         mesg = *ip;
  173.         touch(mesg);
  174.         mp = &message[mesg-1];
  175.         if ((t = send(mp, obuf, 0)) < 0) {
  176.             perror(file);
  177.             fclose(obuf);
  178.             return(1);
  179.         }
  180.         lc += t;
  181.         cc += mp->m_size;
  182.         if (mark)
  183.             mp->m_flag |= MSAVED;
  184.     }
  185.     fflush(obuf);
  186.     if (ferror(obuf))
  187.         perror(file);
  188.     fclose(obuf);
  189.     printf("%s %d/%ld\n", disp, lc, cc);
  190.     return(0);
  191. }
  192.  
  193. /*
  194.  * Write the indicated messages at the end of the passed
  195.  * file name, minus header and trailing blank line.
  196.  */
  197.  
  198. swrite(str)
  199.     char str[];
  200. {
  201.     register int *ip, mesg;
  202.     register struct message *mp;
  203.     register char *file, *disp;
  204.     char linebuf[BUFSIZ];
  205.     int f, *msgvec, lc, cc, t;
  206.     FILE *obuf, *mesf;
  207.     struct stat statb;
  208.  
  209.     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  210.     if ((file = snarf(str, &f)) == NOSTR)
  211.         return(1);
  212.     if ((file = expand(file)) == NOSTR)
  213.         return(1);
  214.     if (!f) {
  215.         *msgvec = first(0, MMNORM);
  216.         if (*msgvec == NULL) {
  217.             printf("No messages to write.\n");
  218.             return(1);
  219.         }
  220.         msgvec[1] = NULL;
  221.     }
  222.     if (f && getmsglist(str, msgvec, 0) < 0)
  223.         return(1);
  224.     printf("\"%s\" ", file);
  225.     fflush(stdout);
  226.     if (stat(file, &statb) >= 0)
  227.         disp = "[Appended]";
  228.     else
  229.         disp = "[New file]";
  230.     if ((obuf = fopen(file, "a")) == NULL) {
  231.         perror(NOSTR);
  232.         return(1);
  233.     }
  234.     cc = lc = 0;
  235.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  236.         mesg = *ip;
  237.         touch(mesg);
  238.         mp = &message[mesg-1];
  239.         mesf = setinput(mp);
  240.         t = mp->m_lines - 1;
  241.         while (t-- > 0) {
  242.             readline(mesf, linebuf);
  243.             if (blankline(linebuf))
  244.                 break;
  245.         }
  246.         while (t-- > 0) {
  247.             fgets(linebuf, BUFSIZ, mesf);
  248.             fputs(linebuf, obuf);
  249.             cc += strlen(linebuf);
  250.         }
  251.         lc += mp->m_lines - 2;
  252.         mp->m_flag |= MSAVED;
  253.     }
  254.     fflush(obuf);
  255.     if (ferror(obuf))
  256.         perror(file);
  257.     fclose(obuf);
  258.     printf("%s %d/%d\n", disp, lc, cc);
  259.     return(0);
  260. }
  261.  
  262. /*
  263.  * Snarf the file from the end of the command line and
  264.  * return a pointer to it.  If there is no file attached,
  265.  * just return NOSTR.  Put a null in front of the file
  266.  * name so that the message list processing won't see it,
  267.  * unless the file name is the only thing on the line, in
  268.  * which case, return 0 in the reference flag variable.
  269.  */
  270.  
  271. char *
  272. snarf(linebuf, flag)
  273.     char linebuf[];
  274.     int *flag;
  275. {
  276.     register char *cp;
  277.  
  278.     *flag = 1;
  279.     cp = strlen(linebuf) + linebuf - 1;
  280.  
  281.     /*
  282.      * Strip away trailing blanks.
  283.      */
  284.  
  285.     while (cp > linebuf && isspace(*cp))
  286.         cp--;
  287.     *++cp = 0;
  288.  
  289.     /*
  290.      * Now search for the beginning of the file name.
  291.      */
  292.  
  293.     while (cp > linebuf && !isspace(*cp))
  294.         cp--;
  295.     if (*cp == '\0') {
  296.         printf("No file specified.\n");
  297.         return(NOSTR);
  298.     }
  299.     if (isspace(*cp))
  300.         *cp++ = 0;
  301.     else
  302.         *flag = 0;
  303.     return(cp);
  304. }
  305.  
  306. /*
  307.  * Delete messages.
  308.  */
  309.  
  310. delete(msgvec)
  311.     int msgvec[];
  312. {
  313.     return(delm(msgvec));
  314. }
  315.  
  316. /*
  317.  * Delete messages, then type the new dot.
  318.  */
  319.  
  320. deltype(msgvec)
  321.     int msgvec[];
  322. {
  323.     int list[2];
  324.     int lastdot;
  325.  
  326.     lastdot = dot - &message[0] + 1;
  327.     if (delm(msgvec) >= 0) {
  328.         list[0] = dot - &message[0];
  329.         list[0]++;
  330.         if (list[0] > lastdot) {
  331.             touch(list[0]);
  332.             list[1] = NULL;
  333.             return(type(list));
  334.         }
  335.         printf("At EOF\n");
  336.         return(0);
  337.     }
  338.     else {
  339.         printf("No more messages\n");
  340.         return(0);
  341.     }
  342. }
  343.  
  344. /*
  345.  * Delete the indicated messages.
  346.  * Set dot to some nice place afterwards.
  347.  * Internal interface.
  348.  */
  349.  
  350. delm(msgvec)
  351.     int *msgvec;
  352. {
  353.     register struct message *mp;
  354.     register *ip, mesg;
  355.     int last;
  356.  
  357.     last = NULL;
  358.     for (ip = msgvec; *ip != NULL; ip++) {
  359.         mesg = *ip;
  360.         touch(mesg);
  361.         mp = &message[mesg-1];
  362.         mp->m_flag |= MDELETED|MTOUCH;
  363.         mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
  364.         last = mesg;
  365.     }
  366.     if (last != NULL) {
  367.         dot = &message[last-1];
  368.         last = first(0, MDELETED);
  369.         if (last != NULL) {
  370.             dot = &message[last-1];
  371.             return(0);
  372.         }
  373.         else {
  374.             dot = &message[0];
  375.             return(-1);
  376.         }
  377.     }
  378.  
  379.     /*
  380.      * Following can't happen -- it keeps lint happy
  381.      */
  382.  
  383.     return(-1);
  384. }
  385.  
  386. /*
  387.  * Undelete the indicated messages.
  388.  */
  389.  
  390. undelete(msgvec)
  391.     int *msgvec;
  392. {
  393.     register struct message *mp;
  394.     register *ip, mesg;
  395.  
  396.     for (ip = msgvec; ip-msgvec < msgCount; ip++) {
  397.         mesg = *ip;
  398.         if (mesg == 0)
  399.             return;
  400.         touch(mesg);
  401.         mp = &message[mesg-1];
  402.         dot = mp;
  403.         mp->m_flag &= ~MDELETED;
  404.     }
  405. }
  406.  
  407. /*
  408.  * Interactively dump core on "core"
  409.  */
  410.  
  411. core()
  412. {
  413.     register int pid;
  414.     union wait status;
  415.  
  416.     if ((pid = vfork()) == -1) {
  417.         perror("fork");
  418.         return(1);
  419.     }
  420.     if (pid == 0) {
  421.         abort();
  422.         _exit(1);
  423.     }
  424.     printf("Okie dokie");
  425.     fflush(stdout);
  426.     while (wait(&status) != pid)
  427.         ;
  428.     if (status.w_coredump)
  429.         printf(" -- Core dumped\n");
  430.     else
  431.         printf("\n");
  432.     return 0;
  433. }
  434.  
  435. /*
  436.  * Clobber as many bytes of stack as the user requests.
  437.  */
  438. clobber(argv)
  439.     char **argv;
  440. {
  441.     register int times;
  442.  
  443.     if (argv[0] == 0)
  444.         times = 1;
  445.     else
  446.         times = (atoi(argv[0]) + 511) / 512;
  447.     clob1(times);
  448. }
  449.  
  450. /*
  451.  * Clobber the stack.
  452.  */
  453. clob1(n)
  454. {
  455.     char buf[512];
  456.     register char *cp;
  457.  
  458.     if (n <= 0)
  459.         return;
  460.     for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
  461.         ;
  462.     clob1(n - 1);
  463. }
  464.  
  465. /*
  466.  * Add the given header fields to the retained list.
  467.  * If no arguments, print the current list of retained fields.
  468.  */
  469. retfield(list)
  470.     char *list[];
  471. {
  472.     char field[BUFSIZ];
  473.     register int h;
  474.     register struct ignore *igp;
  475.     char **ap;
  476.  
  477.     if (argcount(list) == 0)
  478.         return(retshow());
  479.     for (ap = list; *ap != 0; ap++) {
  480.         istrcpy(field, *ap);
  481.  
  482.         if (member(field, retain))
  483.             continue;
  484.  
  485.         h = hash(field);
  486.         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  487.         igp->i_field = calloc((unsigned) strlen(field) + 1,
  488.             sizeof (char));
  489.         strcpy(igp->i_field, field);
  490.         igp->i_link = retain[h];
  491.         retain[h] = igp;
  492.         nretained++;
  493.     }
  494.     return(0);
  495. }
  496.  
  497. /*
  498.  * Print out all currently retained fields.
  499.  */
  500. retshow()
  501. {
  502.     register int h, count;
  503.     struct ignore *igp;
  504.     char **ap, **ring;
  505.     int igcomp();
  506.  
  507.     count = 0;
  508.     for (h = 0; h < HSHSIZE; h++)
  509.         for (igp = retain[h]; igp != 0; igp = igp->i_link)
  510.             count++;
  511.     if (count == 0) {
  512.         printf("No fields currently being retained.\n");
  513.         return(0);
  514.     }
  515.     ring = (char **) salloc((count + 1) * sizeof (char *));
  516.     ap = ring;
  517.     for (h = 0; h < HSHSIZE; h++)
  518.         for (igp = retain[h]; igp != 0; igp = igp->i_link)
  519.             *ap++ = igp->i_field;
  520.     *ap = 0;
  521.     qsort((char *) ring, count, sizeof (char *), igcomp);
  522.     for (ap = ring; *ap != 0; ap++)
  523.         printf("%s\n", *ap);
  524.     return(0);
  525. }
  526.  
  527. /*
  528.  * Add the given header fields to the ignored list.
  529.  * If no arguments, print the current list of ignored fields.
  530.  */
  531. igfield(list)
  532.     char *list[];
  533. {
  534.     char field[BUFSIZ];
  535.     register int h;
  536.     register struct ignore *igp;
  537.     char **ap;
  538.  
  539.     if (argcount(list) == 0)
  540.         return(igshow());
  541.     for (ap = list; *ap != 0; ap++) {
  542.         if (isign(*ap))
  543.             continue;
  544.         istrcpy(field, *ap);
  545.         h = hash(field);
  546.         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  547.         igp->i_field = calloc((unsigned) strlen(field) + 1,
  548.             sizeof (char));
  549.         strcpy(igp->i_field, field);
  550.         igp->i_link = ignore[h];
  551.         ignore[h] = igp;
  552.     }
  553.     return(0);
  554. }
  555.  
  556. /*
  557.  * Print out all currently ignored fields.
  558.  */
  559. igshow()
  560. {
  561.     register int h, count;
  562.     struct ignore *igp;
  563.     char **ap, **ring;
  564.     int igcomp();
  565.  
  566.     count = 0;
  567.     for (h = 0; h < HSHSIZE; h++)
  568.         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  569.             count++;
  570.     if (count == 0) {
  571.         printf("No fields currently being ignored.\n");
  572.         return(0);
  573.     }
  574.     ring = (char **) salloc((count + 1) * sizeof (char *));
  575.     ap = ring;
  576.     for (h = 0; h < HSHSIZE; h++)
  577.         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  578.             *ap++ = igp->i_field;
  579.     *ap = 0;
  580.     qsort((char *) ring, count, sizeof (char *), igcomp);
  581.     for (ap = ring; *ap != 0; ap++)
  582.         printf("%s\n", *ap);
  583.     return(0);
  584. }
  585.  
  586. /*
  587.  * Compare two names for sorting ignored field list.
  588.  */
  589. igcomp(l, r)
  590.     char **l, **r;
  591. {
  592.  
  593.     return(strcmp(*l, *r));
  594. }
  595.